﻿namespace eslib.FileManageLib
{
    /// <summary>
    /// 目录
    /// 集合模式
    /// </summary>
    public class Dir : FileBase
    {
        #region 成员

        /// <summary>
        /// 子集
        /// </summary>
        public List<FileBase> Children { get; private set; } = new();

        public void Clear() => Children.Clear();

        public void RemoveChild(FileBase child) => Children.Remove(child);

        /// <summary>
        /// 添加子集
        /// </summary>
        /// <param name="child"></param>
        public void AddChild(FileBase child)
        {
            child.Parent = this;
            Children.Add(child);
        }


        public Dir Clone()
        {
            Dir newDir = new(Name, (Dir)Parent);
            newDir.Children = Children;
            return newDir;
        }

        public DirSetting Setting { get; set; }

        #endregion




        /// <summary>
        /// 初始化根目录
        /// </summary>
        /// <param name="name">目录名</param>
        public Dir(string name) : base(name, null)
        {
        }

        /// <summary>
        /// 初始化子目录
        /// </summary>
        /// <param name="name">目录名</param>
        /// <param name="parent">父目录</param>
        public Dir(string name, Dir parent) : base(name, parent)
        {
        }


        /// <summary>
        /// 子目录
        /// </summary>
        /// <returns></returns>
        public List<Dir> SubDirs()
        {
            List<Dir> dirs = new();
            foreach (var child in Children)
            {
                if (child is Dir) dirs.Add((Dir)child);
            }
            return dirs;
        }

        public Dir? FindDir(string name)
        {
            return SubDirs().Where(d => d.Name == name).FirstOrDefault();
        }


        /// <summary>
        /// 添加目录，并复制对应的数据（在文件系统中）
        /// </summary>
        /// <param name="name"></param>
        public void AddSubDir(Dir dir)
        {
            string srcPath = dir.FilePath;      //源

            dir.Parent = this;

            Children.Add(dir);

            //文件系统复制
            string descPath = dir.FilePath;       //目标
            DirTool.CreateDir(descPath);      //不存在时创建

            //复制目录中的数据 
            DirTool.DirectoryCopy(srcPath, descPath);

            //自动更新目录内容
            ReloadChildren();
        }


        public List<FileBase> this[string name]
        {
            get
            {
                return Children.Where(f => f.Name == name).ToList();
            }
        }


        public FileItem? FindFile(string name)
        {
            return Files().Where(f => f.Name == name).FirstOrDefault();
        }


        /// <summary>
        /// 文件集
        /// </summary>
        /// <returns></returns>
        public List<FileItem> Files()
        {
            List<FileItem> files = new();
            foreach (var child in Children)
            {
                if (child is FileItem) files.Add((FileItem)child);
            }
            return files;
        }



        public override void Delete()
        {
            //先删除子集
            foreach (var child in Children)
            {
                child.Delete();
            }

            //再删除自身
            Directory.Delete(FilePath);
        }

        /// <summary>
        /// 将自身复制到target
        /// </summary>
        /// <param name="target"></param>
        /// <exception cref="NotImplementedException"></exception>
        public override FileBase CopyTo(Dir target)
        {
            //创建副本
            var newDir = Clone();

            //复制到目标
            target.AddSubDir(newDir);

            return newDir;
        }

        /// <summary>
        /// 将自身移动到target
        /// </summary>
        /// <param name="target"></param>
        /// <exception cref="NotImplementedException"></exception>
        public override FileBase MoveTo(Dir target)
        {
            //复制
            var newDir = CopyTo(target);

            //移除自身
            Delete();

            ((Dir)this.Parent).Children.Remove(this);

            return newDir;
        }



        #region 加载文件系统方法

        /// <summary>
        /// 加载目录下子文件和子目录，构造整个目录结构
        /// </summary>
        /// <returns></returns>
        public void LoadChildren()
        {
            //加载文件
            LoadFiles();

            //加载目录
            LoadDirs();
        }


        /// <summary>
        /// 重新加载
        /// </summary>
        public void ReloadChildren()
        {
            Clear();
            LoadChildren();
        }

        /// <summary>
        /// 加载目录下指定类型子文件和子目录，构造整个目录结构
        /// </summary>
        /// <param name="filters"></param>
        /// <returns></returns>
        public void LoadChildren(string[] filters)
        {
            //加载文件
            LoadFiles(filters);

            //加载目录
            LoadDirs();
        }


        /// <summary>
        /// 加载目录
        /// </summary>
        public void LoadDirs()
        {
            string[] dirs = Directory.GetDirectories(FilePath);
            foreach (var dir in dirs)
            {
                string name = Path.GetFileName(dir);
                Dir ditem = new Dir(name, this);
                Children.Add(ditem);

                //加载子集
                ditem.LoadChildren();
            }
        }


        /// <summary>
        /// 加载所有文件
        /// </summary>
        public void LoadFiles()
        {
            string[] files = Directory.GetFiles(FilePath);
            loadFiles(files);
        }

        /// <summary>
        /// 加载指定类型文件
        /// </summary>
        /// <param name="filter"></param>
        public void LoadFiles(string filter)
        {
            string[] files = Directory.GetFiles(FilePath, filter);
            loadFiles(files);
        }


        /// <summary>
        /// 加载指定类型文件
        /// </summary>
        /// <param name="filter"></param>
        public void LoadFiles(string[] filters)
        {
            foreach (var filter in filters) LoadFiles(filter);
        }

        void loadFiles(string[] files)
        {
            foreach (var file in files)
            {
                string name = Path.GetFileName(file);
                FileItem item = new(name, this);
                Children.Add(item);
            }
        }

        public override void ReName(string name)
        {
            string dir = Path.GetDirectoryName(FilePath);
            string newname = Path.Combine(dir, name);
            Directory.Move(FilePath, newname);

            this.Name = name;

        }

        #endregion


    }
}